/* logic analyzer ll example

   This example代码是公共领域的(或CC0许可,根据您的选择)

   除非适用法律要求或书面同意,本软件按"原样"分发,不提供任何明示或暗示的保证或条件。
*/
/*
 * 标准IRQ处理程序太慢 >2.5微秒
 * 高级别5中断约0.3微秒开始传输
 */

// 包含必要的头文件
// #include "soc/dport_reg.h"
#include "soc/interrupt_reg.h"                 // 中断相关寄存器定义
#include "soc/gpio_reg.h"                      // GPIO相关寄存器定义
#include "soc/soc.h"                           // SoC相关定义
#include "rom/ets_sys.h"                       // ESP32 ROM函数
#include "logic_analyzer_ll.h"                 // 逻辑分析器低层头文件
#include "logic_analyzer_hi_level_interrupt.h" // 高级中断头文件
#include "esp_log.h"                           // ESP日志功能

// 定义高级中断状态结构体变量
hi_interrupt_state_t la_hi_interrupt_state;
// 标记高级中断是否已启动
static int hi_interrupt_started = 0;

// 停止高级中断超时功能，重置为默认模式
void ll_hi_level_triggered_isr_timeout_stop(void)
{
#ifdef CONFIG_ANALYZER_USE_HI_LEVEL_INTERRUPT // 如果配置使用高级中断
    if (hi_interrupt_started)                 // 如果高级中断已启动
    {
        // 在核心上禁用中断 - 恢复DPORT中断映射寄存器原始值
        _DPORT_REG_WRITE(la_hi_interrupt_state.dport_int_map_reg, la_hi_interrupt_state.dport_int_map_data_disable);
        // 清除核心上的GPIO中断使能 - 恢复GPIO配置寄存器原始值
        REG_WRITE(la_hi_interrupt_state.gpio_pin_cfg_reg, la_hi_interrupt_state.gpio_pin_cfg_backup_data);
        hi_interrupt_started = 0; // 标记高级中断已停止
    }
#endif
}

// 分配高级中断(级别5)，保存GPIO和IRQ寄存器，启动中断
void ll_triggered_isr_alloc(void *arg)
{
    ESP_LOGD("AISR", "start"); // 调试日志

    // 对于共享中断(在两个核心上都定义了GPIO引脚中断)
    // 如果中断边沿已预定义并且在核心上启用了中断
    // 中断边沿不会改变???
    uint32_t trigger_edge = (uint32_t)arg;            // 获取触发边沿参数
    la_hi_interrupt_state.gpio_pin_cfg_trig_data = 0; // 初始化GPIO配置触发数据
    // 读取当前GPIO配置寄存器的值作为备份
    la_hi_interrupt_state.gpio_pin_cfg_backup_data = REG_READ(la_hi_interrupt_state.gpio_pin_cfg_reg);
    // 从备份数据中提取当前的触发类型(3位)
    uint32_t tmp_trig = (la_hi_interrupt_state.gpio_pin_cfg_backup_data >> 7) & 0x7;
    // 如果当前没有设置触发类型或中断未启用，则使用传入的触发边沿
    if (tmp_trig == 0 || (la_hi_interrupt_state.gpio_pin_cfg_backup_data & (0x1 << 13)) == 0)
    {
        tmp_trig = trigger_edge;
    }
    // 准备新的GPIO配置数据:触发类型+核心中断使能位
    la_hi_interrupt_state.gpio_pin_cfg_trig_data = (tmp_trig << 7) | la_hi_interrupt_state.gpio_pin_cfg_int_ena_core_bit;

    // 禁用高级中断
    ESP_INTR_DISABLE(HI_INTERRUPT_NUMBER);

    // 配置GPIO中断
    REG_WRITE(la_hi_interrupt_state.gpio_pin_cfg_reg, 0); // 禁用GPIO上的所有中断
    // 清除GPIO中断状态
    REG_WRITE(la_hi_interrupt_state.gpio_stat_clr_reg, la_hi_interrupt_state.gpio_mask);
    // 将GPIO中断路由到高级中断号
    intr_matrix_set(la_hi_interrupt_state.cpu, ETS_GPIO_INTR_SOURCE, HI_INTERRUPT_NUMBER);

    // 启用高级中断
    ESP_INTR_ENABLE(HI_INTERRUPT_NUMBER);

    // 再次清除GPIO中断状态
    REG_WRITE(la_hi_interrupt_state.gpio_stat_clr_reg, la_hi_interrupt_state.gpio_mask);
    // 启用GPIO中断(使用之前准备的配置数据)
    REG_WRITE(la_hi_interrupt_state.gpio_pin_cfg_reg, la_hi_interrupt_state.gpio_pin_cfg_trig_data);

    vTaskDelete(NULL); // 删除当前任务(因为只需要运行一次)
}

// 启动高级中断，确定使用低级别/高级别中断，查找空闲核心IRQ，填充ASM中断处理程序所需的状态结构
void ll_hi_level_triggered_isr_start(int pin_trigger, int trigger_edge)
{
    int int_free_pro = 0; // 标记PRO核心是否有空闲中断
    int int_free_app = 0; // 标记APP核心是否有空闲中断

    if (pin_trigger < 0) // 如果触发引脚无效则返回
        return;

    la_hi_interrupt_state.cpu = 2; // 初始化为无效核心

    // 检查PRO核心(核心0)的GPIO中断映射寄存器
    switch (_DPORT_REG_READ(INTERRUPT_CORE0_GPIO_INTERRUPT_PRO_MAP_REG))
    {
    case 6: // 这些值表示可用的高级中断号
    case 7:
    case 11:
    case 15:
    case 16:
    case 29:
        int_free_pro = 1;              // PRO核心有空闲中断
        la_hi_interrupt_state.cpu = 0; // 使用PRO核心(0)上的高级中断
        break;
    default:
        int_free_pro = 0; // 没有空闲中断
        break;
    }

    // 检查APP核心(核心1)的GPIO中断映射寄存器
    switch (_DPORT_REG_READ(INTERRUPT_CORE1_GPIO_INTERRUPT_PRO_MAP_REG))
    {
    case 6: // 这些值表示可用的高级中断号
    case 7:
    case 11:
    case 15:
    case 16:
    case 29:
        int_free_app = 1;              // APP核心有空闲中断
        la_hi_interrupt_state.cpu = 1; // 使用APP核心(1)上的高级中断
        break;
    default:
        int_free_app = 0; // 没有空闲中断
        break;
    }

    // 记录当前中断映射状态和选择的CPU核心
    ESP_LOGD("TISR", "pro=%ld app=%ld cpu=%ld",
             _DPORT_REG_READ(INTERRUPT_CORE0_GPIO_INTERRUPT_PRO_MAP_REG),
             _DPORT_REG_READ(INTERRUPT_CORE1_GPIO_INTERRUPT_PRO_MAP_REG),
             la_hi_interrupt_state.cpu);

    // 如果两个核心都没有空闲中断(所有GPIO中断都已预定义)-使用慢速GPIO中断
    if ((int_free_app | int_free_pro) == 0)
    {
        ESP_LOGI("TISR", "slow gpio interrupt");
        // 安装默认GPIO中断服务
        gpio_install_isr_service(0);
        // 设置GPIO中断类型
        gpio_set_intr_type(pin_trigger, trigger_edge);
        // 添加GPIO中断处理程序
        gpio_isr_handler_add(pin_trigger, la_ll_trigger_isr, (void *)pin_trigger);
        // 先禁用再启用GPIO中断(确保状态正确)
        gpio_intr_disable(pin_trigger);
        gpio_intr_enable(pin_trigger);
        return;
    }
    else // 有空闲中断，使用快速GPIO中断
    {
        ESP_LOGD("TISR", "fast gpio interrupt");
        hi_interrupt_started = 1; // 标记高级中断已启动

        // 配置高级中断状态结构体
        la_hi_interrupt_state.dport_int_map_data_disable = 6; // 软件中断-禁用GPIO中断的值
        // 根据选择的核心设置DPORT中断映射寄存器地址
        la_hi_interrupt_state.dport_int_map_reg = (la_hi_interrupt_state.cpu == 0) ? INTERRUPT_CORE0_GPIO_INTERRUPT_PRO_MAP_REG : INTERRUPT_CORE1_GPIO_INTERRUPT_PRO_MAP_REG;
        // 设置中断状态寄存器地址(当前未使用)
        la_hi_interrupt_state.dport_int_stat_reg = (la_hi_interrupt_state.cpu == 0) ? INTERRUPT_CORE0_INTR_STATUS_0_REG : INTERRUPT_CORE1_INTR_STATUS_0_REG;
        // 设置GPIO中断掩码(根据引脚号确定是低32还是高8个GPIO)
        la_hi_interrupt_state.gpio_mask = (pin_trigger < 32) ? 1 << pin_trigger : 1 << (pin_trigger - 32);
        // 设置GPIO状态寄存器地址(当前未使用)
        la_hi_interrupt_state.gpio_stat_reg = (pin_trigger < 32) ? GPIO_STATUS_REG : GPIO_STATUS1_REG;
        // 设置GPIO状态清除寄存器地址
        la_hi_interrupt_state.gpio_stat_clr_reg = (pin_trigger < 32) ? GPIO_STATUS_W1TC_REG : GPIO_STATUS1_W1TC_REG;
        // 设置GPIO引脚配置寄存器地址
        la_hi_interrupt_state.gpio_pin_cfg_reg = GPIO_PIN0_REG + (4 * pin_trigger);
        // 设置GPIO配置寄存器中的中断使能位(两个核心都是位13)
        la_hi_interrupt_state.gpio_pin_cfg_int_ena_core_bit = (la_hi_interrupt_state.cpu == 0) ? (1 << 13) : (1 << 13);

        // 设置I2S VSYNC相关寄存器(用于同步)
        la_hi_interrupt_state.i2s_set_vsync_reg = GPIO_FUNC152_IN_SEL_CFG_REG; // I2S0/I2S1
        la_hi_interrupt_state.i2s_set_vsync_bit = HI_INTERRUPT_SET_VSYNC;      // VSYNC位

        // 在空闲核心上创建任务来分配高级中断
        xTaskCreatePinnedToCore(ll_triggered_isr_alloc, "trigg_alloc", 4096,
                                (void *)trigger_edge, 20, NULL, la_hi_interrupt_state.cpu);
    }
}